#ifndef BACKPACK_GAMECONTEXT_H_
#define BACKPACK_GAMECONTEXT_H_

#include "Inventory.hpp"
#include "GameNode.hpp"
#include "ActionVariant.hpp"

#include <string>
#include <queue>

#include <boost/utility.hpp>

namespace backpack {



/**
 * \class ActivityContext context for use in UserActivity objects
 *
 * It provides following functionality:
 * - fetching game state information (inventory, current GameNode)
 * - queueing Actions for later processing
 */
class ActivityContext : boost::noncopyable {
public:
	ActivityContext(Inventory &inventory)
		: m_rInventory(inventory), m_pCurrentNode(NULL) {
	}

	bool inventoryContains(ItemVariant const& item) const {
		return m_rInventory.containsItem(item);
	}
  GameNode const& getCurrentNode() const {
    return *m_pCurrentNode;
  }
  void enqueueAction(ActionVariant const& action) {
		m_queueActions.push(action);
	}
protected:
	std::queue<ActionVariant> m_queueActions;
	Inventory &m_rInventory;
	GameNode const* m_pCurrentNode;
}; // class ActionQueue



/**
 * \class GameContext context for use in Action objects
 *
 * In extends ActivityContext functionality with:
 * - adding items to inventory
 * - changing current node
 */
class GameContext : public ActivityContext {
public:
	GameContext(Inventory &inventory)
    : ActivityContext(inventory) {
	}

	void addToInventory(ItemVariant const& item) {
		m_rInventory.addItem(item);
	}
	void setCurrentNode(GameNode const& node) {
		m_pCurrentNode = &node;
	}
}; // class GameContext



/**
 * \class ExtendedGameContext context for use in GameLoop
 *
 * In extends GameContext with following functionality:
 * - processing actions queue
 * - visiting current node's hot spots
 */
class ExtendedGameContext : public GameContext {
public:
  ExtendedGameContext(Inventory &inventory)
    : GameContext(inventory) {
  }

	template <class ActionVisitor>
	void processActionQueue(ActionVisitor &visitor);

	template <class HotSpotVisitor>
	void exploreCurrentNode(HotSpotVisitor &visitor) const;
}; // class ExtendedGameContext



template <class ActionVisitor>
void ExtendedGameContext::processActionQueue(ActionVisitor &visitor) {
	while (!m_queueActions.empty()) {
    ActionVariant &action = m_queueActions.front();
		action.apply_visitor(visitor);
		m_queueActions.pop();
	}
}

template <class HotSpotVisitor>
void ExtendedGameContext::exploreCurrentNode(HotSpotVisitor &visitor) const {
	m_pCurrentNode->acceptHotspotVisitor(visitor);
}



} // namespace backpack

#endif // BACKPACK_GAMECONTEXT_H_
